//
// Created by hyzh on 2024/4/22.
//
#include "Date.h"

bool Date::operator!=(const Date &d) const{
    return !(*this == d);
}

bool Date::operator==(const Date &d) const{
    return _year == d._year
            && _month == d._month
            && _day == d._day;
}

bool Date::operator>=(const Date &d) const{
    return *this == d || *this > d;
}
bool Date::operator<=(const Date &d) const{
    return !(*this > d);
}

bool Date::operator>(const Date &d) const{
    return _year > d._year
    || _year == d._year && _month > d._month
    || _year == d._year && _month == d._month && _day > d._day;
}

bool Date::operator<(const Date &d) const{
    return !(*this >= d);
}

bool IsLeapYear(int year)
{
    if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
    {
        return true;
    }
    return false;
}

int GetMonthDay(int year, int month)
{
    int arrays[] = {0, 31,28,31,30,31,30,31,31,30,31,30,31};
    if(month == 2 && IsLeapYear(year))
    {
        return 29;
    }
    return arrays[month];
}

Date& Date::operator+=(int day) {
    _day += day;
    while(_day > GetMonthDay(_year, _month))
    {
        _day -= GetMonthDay(_year, _month);
        _month++;
        if(_month == 13)
        {
            _month = 1;
            _year++;
        }
    }

    return *this;
}

Date Date::operator+(int day) const{
    Date tmp(*this);
    tmp += day;
    return tmp;
}

Date& Date::operator++() {
    *this += 1;
    return *this;
}

Date Date::operator++(int) {
    Date tmp(*this);
    *this += 1;
    return tmp;
}

Date& Date::operator-=(int day) {
    _day -= day;
    while(_day <= 0)
    {
        --_month;
        if(_month == 0)
        {
            --_year;
            _month = 12;
        }
        _day += GetMonthDay(_year, _month);
    }

    return *this;
}

Date Date::operator-(int day) const
{
    Date tmp(*this);
    tmp -= day;
    return tmp;
}

// --d1
Date& Date::operator--() {
    *this -= 1;
    return *this;
}

// d1--
Date Date::operator--(int)
{
    Date tmp(*this);
    tmp -= 1;
    return tmp;
}

// d1 - d2 ,默认认为左大右小
int Date::operator-(const Date &d) const{
    Date max = *this;
    Date min = d;
    int flag = 1;
    if(*this < d)
    {
        max = d;
        min = *this;
        flag = -1;
    }

    int n = 0;
    while(min != max) {
        ++min;
        ++n;
    }

    return n * flag;
}

// d1 << out, 不符合使用习惯。
//void Date::operator<<(ostream& out)
//{
//    out << _year << "/" << _month << "/" << _day << endl;
//}

void Date::Print() const{
    std::cout << _year << "/" << _month << "/" << _day << std::endl;
}

bool DateLess(const Date& d1, const Date& d2)
{
    // 类外面又不能直接访问私有成员
};

std::ostream& operator<<(std::ostream& out, const Date& d)
{
    // 1、可以提供getYear,getMonth,getDay函数。
    // 2、在类的外部访问私有成员函数，可以把这个函数定义成类的友元。
    // 友元可以定义在任意位置，只是声明。
    out << d._year << "/" << d._month << "/" << d._day << std::endl;
    return out;
}

std::istream& operator>>(std::istream& in, Date& d)
{
    in >> d._year >> d._month >> d._day;
    return in;
}

const int& Date::func() {
    static int ret;
    return ret;
}

//void PrintF(const SeqList& s)
//{
//    for(size_t i = 0; i < s.size(); ++i)
//    {
//        // err,size和operator[]都是权限的放大
//        std::cout << s[i] << " ";
//    }
//    std::cout << std::endl;
//}

void PrintF(const SeqList& s)
{
    for(size_t i = 0; i < s.size(); ++i)
    {
        // 这里的s[i]++为什么不报错呢？
        // 因为const修饰的是s对象，也即保护的是s对象的成员变量不能被修改
        // 但是s[i]++返回的是成员变量_a指向的元素，是可以被修改的。
        // 但是这不是我们期望的，期望的是const对象不能被修改。如果在函数定义的
        // 位置将返回值修改为const，那么普通对象也不能修改。因此需要写两个
        // 一个const的，一个普通的。
//        s[i]++;
        std::cout << s[i] << " ";
    }
    std::cout << std::endl;
}

void test1()
{
    Date d1(2024,4,22);
    Date d2(2023, 5,14);
    Date d3(d1);
    std::cout << (d1<d2) << std::endl;
    std::cout << (d1>d2) << std::endl;
    std::cout << (d1==d2) << std::endl;
    std::cout << (d3!=d2) << std::endl;
    std::cout << (d3>=d2) << std::endl;
    std::cout << (d3>=d1) << std::endl;
    std::cout << (d3!=d1) << std::endl;
    std::cout << (d3<d2) << std::endl;
}

// 测试日期+天数
void test2()
{
    Date d1(2024, 4, 22);
    d1.Print();
    d1 += 100;
    d1.Print();
}

// 测试日期的比较
void test3()
{
    Date d1(2024, 4,10);
    Date d2(2022, 4,11);

//    d1 < d2;
    std::cout << DateLess(d1, d2) << std::endl;

    // 内置类型语言支持比较
//    int i=0, j =2;
//    i < j;
}

// 测试日期-日期
void test4()
{
    Date d1(2024,5,6);
    Date d2(2023,6,16);
    Date d3(2019,11,28);
    std::cout << d1 - d2 << std::endl;
    std::cout << d1 - d3 << std::endl;
}

// 测试日期-天数
void test5()
{
    Date d1(2024,5,6);
    d1 -= 2000;
    d1.Print();

    Date d2(2024,6,1);
    d2--;
    d2.Print();
}

void test6()
{
    const Date d1(2024,5,6);
    d1.Print();

    Date d2(2023,10,1);
    d2.func();
}

void test7()
{
    Date d1(2024,5,6);
    Date d2(2024,5,7);
    std::cout << d1;
    std::cout << d1 << d2;
//    d1<<std::cout;

    Date d3;
    std::cin >> d3;
    std::cout << d3;
}




